1/* <The name of this game>, by <your name goes here>. */
    2
    3:- dynamic i_am_at/1, at/2, holding/1, status/1, not_destroyed/1.    4:- retractall(at(_, _)), retractall(i_am_at(_)), retractall(alive(_)).    5
    6/* create a closet that needs to be destroyed to continue */
    7not_destroyed(closet).
    8
    9i_am_at(bedroom).
   10%i_am_at(school). % for testing purposes
   11
   12/* create paths linking rooms to each other. */
   13path(bedroom , n, bathroom).
   14path(bedroom , s, kitchen).
   15path(bedroom, e, closet).
   16
   17path(closet, w, bedroom).
   18
   19path(kitchen, n, bedroom).
   20
   21/* Need to be wearing a suit or a fancy suit while holding a lunch to walk out the door */
   22path(kitchen, s, school):- (status(suit); status(fancy_suit), holding(sack_lunch)).
   23path(kitchen, s, school):-
   24	status(pajamas),
   25	writeln('Those are some really frilly pajamas.'),
   26	writeln('It would be a close second to being naked at school.'),
   27	writeln('Get dressed!'),
   28	!, fail.
   29path(kitchen, s, school):-
   30	writeln('School is long and hard.  You should pack a lunch in a bag.'),
   31	!, fail.
   32
   33path(bathroom , s, bedroom).
   34path(bathroom , e, shower).
   35path(bathroom , w, toilet).
   36
   37path(shower, w, bathroom).
   38path(toilet, e, bathroom).
   39
   40path(school, s, classroom1).
   41path(classroom1, e, quiz_room):-
   42	writeln('Think you''r a smarty pants?').
   43
   44/* Setting up the quiz rooms, here how you get somewhere matters (for points) */
   45path(classroom1, w, quiz_room):-
   46	writeln('Ha got you!  Detention is too good for you.'),
   47	writeln('Off to take a quiz.').
   48
   49path(quiz_room, s, question1).
   50
   51path(question1, e, question2):-
   52	writeln('Hmm, maybe that was too easy!'),
   53	writeln('Minus 1 life!'),
   54        subtract_life(1).
   55
   56
   57path(question1, w, question2):-
   58	writeln('Ha got you! Again!'),
   59	writeln('Minus 2 lives for you!'),
   60        subtract_life(2).
   61
   62path(question2, e, question3):-
   63	writeln('A lucky guess!'),
   64	writeln('Minus 1 life!'),
   65        subtract_life(1).
   66
   67
   68path(question2, w, question3):-
   69	writeln('WRONG. Who knows this stuff anyway?  Except, it''s on a test!'),
   70	writeln('Minus 2 lives for you!'),
   71        subtract_life(2).
   72
   73path(question3, e, lunchroom):-
   74	writeln('Why would you count the stars anyway.'),
   75	writeln('Fine.  Go to lunch.').
   76
   77path(question3, w, lunchroom):-
   78	writeln('WRONG. Guess someone was bored.'),
   79	writeln('Minus 2 lives for you!'),
   80        subtract_life(2).
   81
   82
   83path(_, _).
   84
   85/* place items in the world */
   86at(plain_bread, kitchen).
   87at(water, kitchen).
   88at(bottle, kitchen).
   89
   90/* person status, for internal states */
   91status(need_to_pee).
   92status(pajamas).
   93status(alive).
   94
   95/* declare list of things that person can use. */
   96use(suit):-
   97	holding(suit),
   98	status(wet),
   99	writeln('Too wet from shower! This will destroy the suit.').
  100use(suit) :-
  101	holding(suit),
  102	retract(holding(suit)),
  103	writeln('You feel like ready to tackle the world.'),
  104	retract(status(pajamas)),
  105	assert(status(suit)).
  106
  107use(tie) :-
  108	holding(tie),
  109	status(suit),
  110
  111	retract(status(suit)),
  112	assert(status(fancy_suit)),
  113	writeln('My my, someone looks dashing!').
  114
  115use(tie):-
  116	holding(tie),
  117        writeln('It might be better to put something on first.'),
  118	writeln('This is a school after all').
  119
  120
  121use(towel):-
  122	status(wet),
  123	retract(status(wet)),
  124	writeln('All dry now!').
  125use(towel) :-
  126	writeln('Already dry.').
  127
  128use(_) :-
  129	writeln('You can''t use that!').
  130
  131
  132/* things that can be combined together to create new items */
  133combine(plain_bread, bottled_water):-
  134	holding(bottled_water),
  135	holding(plain_bread),
  136	writeln('You just made a sack lunch!'),
  137	retract(holding(bottled_water)),
  138	retract(holding(plain_bread)),
  139	assert(holding(sack_lunch)).
  140
  141
  142combine(bottled_water, plain_bread):-
  143	holding(bottled_water),
  144	holding(plain_bread),
  145	writeln('You just made a sack lunch!'),
  146	retract(holding(bottled_water)),
  147	retract(holding(plain_bread)),
  148	assert(holding(sack_lunch)).
  149
  150combine(water, bottle):-
  151	holding(bottle),
  152	holding(water),
  153	writeln('You just made bottled_water!'),
  154	retract(holding(bottle)),
  155	retract(holding(water)),
  156	assert(holding(bottled_water)).
  157
  158combine(bottle, water):-
  159	holding(bottle),
  160	holding(water),
  161	writeln('You just made bottled_water!'),
  162	retract(holding(bottle)),
  163	retract(holding(water)),
  164	assert(holding(bottled_water)).
  165
  166combine(suit, tie) :-
  167	holding(suit),
  168	holding(tie),
  169	writeln('That is one heck of a fancy suit.'),
  170	retract(holding(suit)),
  171	retract(holding(tie)),
  172	assert(holding(fancy_suit)).
  173
  174combine(item1, item2) :-
  175	holding(item1), holding(item2),
  176	writeln('These do not combine!').
  177
  178combine(_, _) :-
  179	writeln('Are you sure you have both ingredients?').
  180
  181/* These rules describe how to pick up an object. */
  182take(X) :-
  183        holding(X),
  184        writeln('You''re already holding it!'),
  185        !.
  186
  187take(X) :-
  188        i_am_at(Place),
  189        at(X, Place),
  190        retract(at(X, Place)),
  191        assert(holding(X)),
  192        writeln('OK.'),
  193        !.
  194
  195take(_) :-
  196        writeln('I don''t see it here.'),
  197        nl, fail.
  198
  199
  200/* These rules describe how to put down an object. */
  201
  202drop(X) :-
  203        holding(X),
  204        i_am_at(Place),
  205        retract(holding(X)),
  206        assert(at(X, Place)),
  207        writeln('OK.'),
  208        !.
  209
  210drop(_) :-
  211        writeln('You aren''t holding it!'),
  212        nl.
  213
  214
  215/* a life counter for quiz section */
  216subtract_life(X):-
  217    nb_getval(life, Life),
  218    Nlife is Life - X,
  219    nb_setval(life, Nlife),
  220    Nlife =< 0,
  221    retract(status(alive)),!,
  222    fail.
  223
  224
  225
  226subtract_life(_).
  227
  228/* see life counter */
  229display_life :-
  230	nb_getval(life, Life),
  231	write('You have '), write(Life), writeln(' remaining.').
  232
  233
  234/* These rules define the direction letters as calls to go/1. */
  235
  236n :- go(n).
  237
  238s :- go(s).
  239
  240e :- go(e).
  241
  242w :- go(w).
  243
  244i :- inventory.
  245
  246/* This rule tells how to move in a given direction. */
  247
  248go(Direction) :-
  249	status(alive),
  250        i_am_at(Here),
  251        path(Here, Direction, There),
  252        retract(i_am_at(Here)),
  253        assert(i_am_at(There)),
  254        !, look.
  255
  256go(_) :-
  257	status(alive),
  258        writeln('You can''t go that way.').
  259
  260go(_) :-
  261        i_am_at(Here),
  262        retract(i_am_at(Here)),
  263        assert(i_am_at(death)),
  264	!, look.
  265
  266/* This rule tells how to look about you. */
  267
  268look :-
  269        i_am_at(Place),
  270        describe(Place),
  271        nl,
  272        notice_objects_at(Place),
  273        nl.
  274
  275/* These rules set up a loop to mention all the objects
  276   in your vicinity. */
  277
  278notice_objects_at(Place) :-
  279        at(X, Place),
  280        write('There is a '), write(X), write(' here.'), nl,
  281        fail.
  282
  283notice_objects_at(_).
  284
  285/* These rules set up a loop to mention all objects in inventory. */
  286inventory :-
  287	writeln('You own: '),
  288	list_inventory.
  289
  290inventory :-
  291	writeln('You own nothing!').
  292
  293list_inventory:-
  294	holding(X),
  295	writeln(X), fail.
  296list_inventory.
  297
  298/* This is for internal use to debug*/
  299my_status :-
  300	writeln('Currently in state: '),
  301	list_status.
  302
  303list_status:-
  304	status(X),
  305	writeln(X), fail.
  306list_status.
  307
  308
  309
  310
  311/* Under UNIX, the "halt." command quits Prolog but does not
  312   remove the output window. On a PC, however, the window
  313   disappears before the final output can be seen. Hence this
  314   routine requests the user to perform the final "halt." */
  315
  316finish :-
  317        nl,
  318        writeln('The game is over. Please enter the "halt." command.'),
  319        nl.
  320
  321
  322/* This rule just writelns out game instructions. */
  323
  324instructions :-
  325        nl,
  326        writeln('Enter commands using standard Prolog syntax.'),
  327        writeln('Available commands are:'),
  328        writeln('start.             -- to start the game.'),
  329        writeln('n.  s.  e.  w.     -- to go in that direction.'),
  330        writeln('take(Object).      -- to pick up an object.'),
  331        writeln('drop(Object).      -- to put down an object.'),
  332        writeln('look.              -- to look around you again.'),
  333	writeln('inventory or i     -- to view your current inventory.'),
  334	writeln('combine(Item1, Item2) -- to make new items from inventory.'),
  335	writeln('use(Item1)         -- use item in inventory'),
  336
  337	writeln('instructions.      -- to see this message again.'),
  338        writeln('halt.              -- to end the game and quit.'),
  339        nl.
  340
  341/* This rule prints out instructions and tells where you are. */
  342
  343start :-
  344        instructions,
  345        look.
  346
  347
  348/* These rules describe the various rooms.  Depending on
  349   circumstances, a room may have more than one description. */
  350
  351describe(bedroom) :-
  352	writeln('It is a school day.'),
  353	writeln('n -- go to the bathroom.'),
  354	writeln('s -- go to the kitchen.'),
  355	writeln('e -- go to the closet.').
  356
  357
  358describe(kitchen):-
  359	writeln('The kitchen smells like baking bread.'),
  360        writeln('n -- return to bedroom'),
  361	writeln('s -- head to school!').
  362
  363describe(closet):-
  364	not_destroyed(closet),
  365	status(wet),
  366	writeln('AIIIEEEEEE.  The door is melting!'),nl,
  367        retract(not_destroyed(closet)),
  368
  369        assert(at(towel, closet)),
  370        assert(at(suit, closet)),
  371        assert(at(tie, closet)),
  372
  373        describe(closet).
  374
  375
  376describe(closet):-
  377	not_destroyed(closet),
  378
  379	writeln('The closet is closed.'),
  380	writeln('This closet is immune to earth, fire, air.'),
  381	writeln('w -- back to bedroom.'), !, fail.
  382
  383
  384describe(closet):-
  385	writeln('The closet is musty.  You should clean it at some point.'),
  386	writeln('But you can do that tomorrow.'),
  387
  388	writeln('w -- back to bedroom.').
  389
  390
  391describe(bathroom) :-
  392	writeln('You are in the bathroom!'),
  393	writeln('s -- back to bedroom'),
  394	writeln('e -- to shower.'),
  395	writeln('w -- to use the toilet.').
  396
  397describe(shower):-
  398	writeln('A nice warm shower shower wakes you up fully.'),
  399	writeln('You emerge from the shower dripping wet.'),
  400	writeln('w -- return to bathroom'),
  401
  402	assert(status(wet)),
  403
  404	status(smelly),
  405	retract(status(smelly)).
  406
  407
  408describe(toilet):-
  409	status(need_to_pee),
  410	writeln('Well that felt nice!'),
  411	retract(status(need_to_pee)),
  412
  413	writeln('e -- return to bathroom').
  414
  415describe(toilet) :-
  416	writeln('I don''t need to pee.'),
  417	writeln('e -- return to bathroom').
  418
  419describe(school) :-
  420	writeln('Here be dragons.  Enter at your own risk.'),
  421	writeln('s -- Enter').
  422
  423
  424describe(classroom1) :-
  425	writeln('Welcome to your first class of the day!'),
  426	writeln('You in the fancy suit!'),
  427	writeln('Pop quiz or detention?'),
  428
  429	writeln('e -- for pop quiz'),nl,
  430	writeln('w -- for detention').
  431
  432describe(quiz_room) :-
  433	writeln('Welcome to the quiz room!'),
  434	writeln('The rules are simple.'),
  435	writeln('You have 3 lives.'),
  436	writeln('Answer correctly, 1 penalty.'),
  437	writeln('Answer incorrectly, 2 penalty.'),
  438	writeln('You run out of lives, you don''t make it to lunch.'),nl,
  439
  440	writeln('Ready?'),nl,
  441
  442	nb_setval(life, 3),
  443
  444
  445	writeln('s -- take a quiz').
  446
  447describe(question1):-
  448	display_life,
  449
  450        writeln('What is 1 + 1?'),
  451
  452	writeln('e -- 2.  That was easy!'),
  453	writeln('w -- Not 2.').
  454
  455describe(question2):-
  456	display_life,
  457
  458        writeln('What is the capital of Zimbabwe?'),
  459
  460	writeln('e -- Harare.'),
  461	writeln('w -- Abuja.').
  462
  463describe(question3):-
  464	display_life,
  465
  466        writeln('Are there more sand grains on Earth than stars in the sky?'),
  467
  468	writeln('e -- No.'),
  469	writeln('w -- Yes.').
  470
  471describe(lunchroom):-
  472	writeln('Congrats on making it to the lunch room.'),
  473	writeln('As you eat your plain bread and drink your water.'),
  474	writeln('You contemplate whether or not it is worth'),
  475	writeln('playing the sequel:  Classroom 2:  Recess'),
  476	finish, !.
  477
  478describe(death):-
  479	writeln('Rightly or wrongly you have failed to last 1 day in school.'),
  480	writeln('Try again?'),
  481	finish